﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Threading;
using System.Windows;
using Utility;

namespace MyGestures
{
    /// <summary>
    /// App.xaml 的交互逻辑
    /// </summary>
    public partial class App : Application
    {
        #region properties
        /// <summary>
        /// 托盘区图标
        /// </summary>
        private NotifyIcon notifyIcon;

        private Rectangle fullscreen = Common.GetFullscreen();

        /// <summary>
        /// 鼠标位置队列
        /// </summary>
        private Queue<System.Drawing.Point> mousePosQueue = new Queue<System.Drawing.Point>();

        /// <summary>
        /// 当前鼠标位置
        /// </summary>
        private System.Drawing.Point mousePoint;

        /// <summary>
        /// 最后一个有效的坐标
        /// </summary>
        private System.Drawing.Point? lastValidPoint = null;

        /// <summary>
        /// 用户设置
        /// </summary>
        private List<MouseStruct> mouseConfig;
        #endregion

        private volatile bool continueThread = true;
        private GameMonitor monitor;
        #region methods
        /// <summary>
        /// 主函数入口
        /// </summary>
        /// <param name="sender">应用程序对象</param>
        /// <param name="EventArgs">命令行参数</param>
        private App()
        {
            try
            {
                Common.IsStart();
                Common.CheckFile(new string[] { "Utility.dll" });
                if (!File.Exists("MyGesture.config"))
                {
                    SerializeDefaultConfig();
                }
                mouseConfig = JsonSerializer.DeserializeFromFile<List<MouseStruct>>("MyGesture.config");

                notifyIcon = new NotifyIcon(new System.Windows.Forms.ContextMenu(new System.Windows.Forms.MenuItem[]
                {
                    new System.Windows.Forms.MenuItem("开机自启", ((s,e)=>
                    {
                        if (s is System.Windows.Forms.MenuItem m)
                        {
                            if (m.Checked)
                            {
                                ShortCut.Delete();
                            }
                            else
                            {
                                ShortCut.Create();
                            }
                            m.Checked = !m.Checked;
                        }
                    }))
                    {
                        Checked = ShortCut.Exists()
                    },
                    new System.Windows.Forms.MenuItem("退出", ((s,e) =>
                    {
                        Current.Shutdown();
                    }))
                }), "Icon.ico");

                GetMousePosLoop();
                TreatMousePosLoop();

                monitor = new GameMonitor(() => continueThread = false, () => continueThread = true);

                Exit += ((s, e) =>
                {
                    notifyIcon.Close();
                    Environment.Exit(0);
                });
            }
            catch (StartException Exception)
            {
                MessageBox.Show($"应用程序初始化失败!QAQ\n请重启程序或联系作者\n出错函数:{Exception.Function}\n额外信息:{Exception.Message}");
                Current.Shutdown();
            }
            catch (Exception Exception)
            {
                MessageBox.Show($"应用程序出现异常:{Exception}");
                Debug.Print(Exception.ToString());
            }
        }

        /// <summary>
        /// 启动一个获取当前鼠标坐标的线程
        /// </summary>
        void GetMousePosLoop() =>
            new Thread(() =>
            {
                while (true)
                {
                    while (!continueThread) ;
                    WinAPI.GetCursorPos(out System.Drawing.Point MousePoint);
                    lock (mousePosQueue)
                    {
                        mousePosQueue.Enqueue(MousePoint);
                        Monitor.Pulse(mousePosQueue);
                    }
                    Thread.Sleep(10);
                    //Debug.Print($"当前鼠标坐标:{MousePoint}");
                }
            })
            {
                IsBackground = true
            }.Start();

        /// <summary>
        /// 启动一个处理当前鼠标坐标的线程
        /// </summary>
        void TreatMousePosLoop() =>
            new Thread(() =>
            {
                while (true)
                {
                    lock (mousePosQueue)
                    {
                        if (mousePosQueue.Count == 0)
                        {
                            Monitor.Wait(mousePosQueue);
                        }
                        mousePoint = mousePosQueue.Dequeue();
                    }

                    if (lastValidPoint != null && PointDistance(mousePoint, (System.Drawing.Point)lastValidPoint) < 50)
                    {
                        continue;
                    }
                    else
                    {
                        lastValidPoint = null;
                    }

                    foreach (MouseStruct MouseStruct in mouseConfig)
                    {
                        if (PointDistance(mousePoint, MouseStruct.Point) < MouseStruct.Distance)
                        {
                            foreach (MouseStructItem item in MouseStruct.MouseItem)
                            {
                                WinAPI.KeybdEvent(item.Vk, 0, item.KeyEvent, 0);
                            }
                            Debug.Print($"有效鼠标坐标:{mousePoint}");
                            lastValidPoint = mousePoint;
                        }
                    }
                }
            })
            {
                //Priority = ThreadPriority.BelowNormal,
                IsBackground = true
            }.Start();

        /// <summary>
        /// 求两点间距离
        /// </summary>
        /// <param name="Point1"></param>
        /// <param name="Point2"></param>
        /// <returns></returns>
        double PointDistance(System.Drawing.Point Point1, System.Drawing.Point Point2) =>
            Math.Sqrt((Point1.X - Point2.X) * (Point1.X - Point2.X) + (Point1.Y - Point2.Y) * (Point1.Y - Point2.Y));

        /// <summary>
        /// 将默认配置写入<see cref="Config"/>文件中
        /// </summary>
        public void SerializeDefaultConfig()
        {
            MouseStructItem[][] MouseStructItemArray = new MouseStructItem[][]
            {
                new MouseStructItem[]
                {
                    new MouseStructItem()
                    {
                        Vk = WinAPI.VK.LWIN,
                        KeyEvent = WinAPI.KeyEvent.KeyDown
                    },
                    new MouseStructItem()
                    {
                        Vk = WinAPI.VK.TAB,
                        KeyEvent = WinAPI.KeyEvent.KeyDown
                    },
                    new MouseStructItem()
                    {
                        Vk = WinAPI.VK.TAB,
                        KeyEvent = WinAPI.KeyEvent.KeyUp
                    },
                    new MouseStructItem()
                    {
                        Vk = WinAPI.VK.LWIN,
                        KeyEvent = WinAPI.KeyEvent.KeyUp
                    }
                },
                new MouseStructItem[]
                {
                    new MouseStructItem()
                    {
                        Vk = WinAPI.VK.LWIN,
                        KeyEvent = WinAPI.KeyEvent.KeyDown
                    },
                    new MouseStructItem()
                    {
                        Vk = WinAPI.VK.LWIN,
                        KeyEvent = WinAPI.KeyEvent.KeyUp
                    }
                },
                new MouseStructItem[]
                {
                    new MouseStructItem()
                    {
                        Vk = WinAPI.VK.LWIN,
                        KeyEvent = WinAPI.KeyEvent.KeyDown
                    },
                    new MouseStructItem()
                    {
                        Vk = WinAPI.VK.D,
                        KeyEvent = WinAPI.KeyEvent.KeyDown
                    },
                    new MouseStructItem()
                    {
                        Vk = WinAPI.VK.D,
                        KeyEvent = WinAPI.KeyEvent.KeyUp
                    },
                    new MouseStructItem()
                    {
                        Vk = WinAPI.VK.LWIN,
                        KeyEvent = WinAPI.KeyEvent.KeyUp
                    }
                }
            };

            List<MouseStruct> MouseStructList = new List<MouseStruct>(3);
            foreach (var point in new System.Drawing.Point[]
            {
                new System.Drawing.Point()
                {
                    X = 0,
                    Y = 0
                },
                new System.Drawing.Point()
                {
                    X = 0,
                    Y = fullscreen.Height
                },
                new System.Drawing.Point()
                {
                    X = fullscreen.Width,
                    Y = fullscreen.Height
                }
            })
            {
                MouseStructList.Add(new MouseStruct()
                {
                    Point = point,
                    Distance = 10,
                    MouseItem = new List<MouseStructItem>()
                });
                foreach (MouseStructItem item in MouseStructItemArray[MouseStructList.Count - 1])
                {
                    MouseStructList[MouseStructList.Count - 1].MouseItem.Add(item);
                }
            }
            JsonSerializer.SerializeToFile(MouseStructList, "MyGesture.config");
        }
        #endregion
    }
}